﻿namespace TestApplication2
{
    #region Namespaces
    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using System.Windows;

    #endregion

    /// <summary>
    ///     Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();
        }

        /// <summary>
        ///     Handles the Click event of the buttonStart control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs" /> instance containing the event data.</param>
        private async void OnButtonStartClick(object sender, RoutedEventArgs e)
        {
            buttonStart.IsEnabled = false;
            Process firstApplication = null, secondApplication = null, newFirstApplication = null, thirdApplication = null;

            MessageBox.Show(this, "The first instance aware application is going to be launched...", "Composite test - Step 1");
            firstApplication = SpawnApplication();

            if (firstApplication != null)
            {
                MessageBox.Show(this, "A second application is going to be launched (with some parameters)...", "Composite test - Step 2");
                secondApplication = SpawnApplication("those are some args");

                if (secondApplication != null)
                {
                    await TaskEx.Delay(TimeSpan.FromSeconds(2)); //Just wait a couple of seconds, to ensure that this message box is on top of the others (ugly!)
                    MessageBox.Show(this, "Now the first application will be killed, while the second is still running...", "Composite test - Step 3");
                    try
                    {
                        try
                        {
                            firstApplication.Kill();
                        }
                        catch (InvalidOperationException exc)
                        {
                            Debug.WriteLine("The first process has been already shutdown" + Environment.NewLine + exc,
                                            GetType()
                                                    .ToString());
                        }

                        MessageBox.Show(this,
                                        "A new application will be spawned and will be considered as the first application." + Environment.NewLine +
                                        "This behavior is caused by the fact that the check is performed at startup time *only*... moreover in a typical scenario the 'second' application will close as soon as it discovers that a previous instance is already running.",
                                        "Composite test - Step 4");
                        newFirstApplication = SpawnApplication("relinquish=5");

                        if (newFirstApplication != null)
                        {
                            MessageBox.Show(this, "The current 'first' application will relinquish its role in 5 seconds, allowing for a new application to take over it.", "Composite test - Step 5");
                            await TaskEx.Delay(TimeSpan.FromSeconds(5));

                            thirdApplication = SpawnApplication("some more args");

                            if (thirdApplication != null)
                                MessageBox.Show(this, "The test completed successfully!", "Composite test - End");
                            else
                                MessageBox.Show(this, "Could not start the new first application", "Composite test - Error");
                        }
                        else
                            MessageBox.Show(this, "Could not start the new first application", "Composite test - Error");
                    }
                    catch (Exception exc)
                    {
                        MessageBox.Show(this, "Unexpected exception while executing the test" + Environment.NewLine + exc, "Composite test - Error");
                    }
                }
                else
                    MessageBox.Show(this, "Could not start the second application", "Composite test - Error");
            }
            else
                MessageBox.Show(this, "Could not start the first application", "Composite test - Error");

            try
            {
                if (secondApplication != null)
                    secondApplication.Kill();
                if (newFirstApplication != null)
                    newFirstApplication.Kill();
                if (thirdApplication != null)
                    thirdApplication.Kill();
            }
            catch (InvalidOperationException exc)
            {
                Debug.WriteLine("One of the processes has been already shutdown" + Environment.NewLine + exc,
                                GetType()
                                        .ToString());
            }
            buttonStart.IsEnabled = true;
        }

        /// <summary>
        ///     Spawns an application.
        /// </summary>
        /// <param name="args">The arguments of the application to spawn.</param>
        /// <returns>
        ///     The application or <c>null</c> if an error occurred.
        /// </returns>
        private Process SpawnApplication(string args = null)
        {
            Process application;
            try
            {
                application = Process.Start(typeof(TestApplication.App).Assembly.Location, args);
            }
            catch (Exception exc)
            {
                MessageBox.Show(this, "An exception was raised while launching the application!" + Environment.NewLine + exc);
                return null;
            }

            return application;
        }
    }
}